
#ifndef LOD_JEFF_CAMERA_H
#define LOD_JEFF_CAMERA_H

// based on glmodelwin from Simplification Viewer by Jeff Somers

#include "base/point3.h"
#include <cmath>

//todo
#include <iostream>
using std::cout;
using std::endl;

class jeff_camera
{

    public:
    jeff_camera()
     : oldX_(0), oldY_(0), newX_(0), newY_(0)
    {
        resetOrientation();
    }

    void resetOrientation()
    {
        elevation_ = ORIG_ELEVATION;
        azimuth_ = ORIG_AZIMUTH;
        dist_ = ORIG_DIST;
    }

    void mouseMotion(int x, int y, int width, int height, bool rotation, bool distance)
    {
        oldX_ = newX_; 
        oldY_ = newY_;
        newX_ = x;  
        newY_ = y; 

        if (newX_ & 0x1000) newX_ = -(0xFFFF - newX_); // when move mouse up, turns from 0 to 65535
        if (newY_ & 0x1000) newY_ = -(0xFFFF - newY_); // turn an unsigned value to a signed value so math works

        float RelX = (newX_ - oldX_) / (float)width;
        float RelY = (newY_ - oldY_) / (float)height;

        // Change distance
        if (distance) 
        {
                dist_ += 10 * RelY;

                if (dist_ > MAX_DISTANCE) dist_ = MAX_DISTANCE;
                if (dist_ < MIN_DISTANCE) dist_ = MIN_DISTANCE;
        // Rotation
        } 
        else if (rotation)
        { // left button down
                azimuth_ += (RelX*180);
                elevation_ += (RelY*180);
        }
        //cout<<"a "<<azimuth_<<endl;
        //cout<<"e "<<elevation_<<endl;
        //cout<<"d "<<dist_<<endl;
    }

    float get_dist()
    {
        return dist_;
    }

    float get_elevation()
    {
        return elevation_;
    }

    float get_azimuth()
    {
        return azimuth_;
    }

    void set_dist(float dist)
    {
        if (dist > MAX_DISTANCE) dist_ = MAX_DISTANCE;
        else if (dist < MIN_DISTANCE) dist_ = MIN_DISTANCE;
        else dist_ = dist;
    }


    point3<float> get_cartesian_co()
    {
        point3<float> eye;
        //eye.x = dist_ * std::cos(theta) * std::cos(phi);
        //eye.y = distance * std::cos(theta) * std::sin(phi);
        //eye.z = distance * std::sin(theta);
        eye.z = dist_ * std::cos(elevation_/180*M_PI) * std::cos(azimuth_/180*M_PI);
        eye.x = dist_ * std::cos(elevation_/180*M_PI) * -std::sin(azimuth_/180*M_PI);
        eye.y = dist_ * std::sin(elevation_/180*M_PI);
        return eye;
    }



    private:
    // Mesh orientation variables
    float elevation_;
    float azimuth_;
    float dist_;

    // Model orientation
    static const float ORIG_ELEVATION = 0.0f;
    static const float ORIG_AZIMUTH = 0.0f;
    static const float ORIG_DIST = 3.0f;

    // used for mouse motion
    int oldX_, oldY_, newX_, newY_;

    public:
    static const float MIN_DISTANCE = 0.1f;
    static const float MAX_DISTANCE = 100.0f;
};

#endif // LOD_JEFF_CAMERA_H

